package com.tomorrow.runner.data;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.provider.BaseColumns;
import android.util.SparseArray;

import java.lang.reflect.Field;

import cn.sucun.android.utils.SQLUtility;

/**
 *
 * @param <T>
 *            create at 2014-8-13 上午11:11:45
 */
public class SimpleProvider<T extends ContentProvider> extends AbsSubProvider<T> {

	// database name
	private final String DATABASE;
	// database version
	private final int DATABASE_VERSION;
	// table name
	private final String TABLE_NAME;
	// access table ,in uri the table content name
	private final String CONTENT_NAME;
	// the sqliteOpenHelper
	private final DatabaseHelper.DBBuilder BUILDER;
	// table id column
	private final String _ID;

	// match dir
	protected int MATCH_DIR;
	// match item
	protected int MATCH_ITEM;

	protected DatabaseHelper mOpenHelper;

	// If the class do not have the same name Field ,there will throw exception
	public SimpleProvider(T parent, String authority,
						  Class<? extends BaseColumns> clazz) {
		super(parent, authority);
		try {
			Field f = clazz.getField("DATABASE");
			DATABASE = (String) f.get(null);

			f = clazz.getField("DATABASE_VERSION");
			DATABASE_VERSION = f.getInt(null);

			f = clazz.getField("TABLE_NAME");
			TABLE_NAME = (String) f.get(null);

			f = clazz.getField("BUILDER");
			BUILDER = (DatabaseHelper.DBBuilder) f.get(null);

			f = clazz.getField("CONTENT_NAME");
			CONTENT_NAME = (String) f.get(null);

			f = clazz.getField("_ID");
			_ID = (String) f.get(null);
		} catch (Exception e) {
			throw new IllegalArgumentException(
					"Target class should define DATABASE, DATABASE_VERSION, "
							+ "TABLE_NAME, BUILDER, CONTENT_NAME & _ID");
		}
	}

	/**
	 * register this content provider into match ContentProvider list when user
	 * call insert etc function , SucunProvider match the uri the choose the
	 * AbsContentproviderImpl to deal with the user call
	 */
	@Override
	protected int registerMatch(UriMatcher matcher, int offset) {
		int count = 0;
		MATCH_DIR = offset + count++;
		MATCH_ITEM = offset + count++;

		matcher.addURI(mAuthority, CONTENT_NAME, MATCH_DIR);
		matcher.addURI(mAuthority, CONTENT_NAME + "/#", MATCH_ITEM);
		return count;
	}

	@Override
	protected void registerSQLiteOpenHelper(
			SparseArray<SQLiteOpenHelper> openHelpers) {
		if (mOpenHelper == null) {
			mOpenHelper = new DatabaseHelper(mContext, DATABASE,
					DATABASE_VERSION, BUILDER);
		}

		openHelpers.put(MATCH_DIR, mOpenHelper);
		openHelpers.put(MATCH_ITEM, mOpenHelper);
	}

	@Override
	protected void shutdown() {
		if (mOpenHelper != null) {
			mOpenHelper.close();
			mOpenHelper = null;
		}
	}

	@Override
	public String getType(Uri uri, int match) {
		String result;
		if (match == MATCH_DIR) {
			result = DIR_BASE_TYPE + "." + CONTENT_NAME;
		} else {
			result = ITEM_BASE_TYPE + "." + CONTENT_NAME;
		}
		return result;
	}

	@Override
	public Cursor query(SQLiteDatabase db, int match, Uri uri,
						String[] projection, String selection, String[] selectionArgs,
						String sortOrder) {

		if (match == MATCH_ITEM) {
			long id = ContentUris.parseId(uri);
			selection = SQLUtility.and(_ID + "=" + id, selection);
		}

		SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
		qb.setTables(TABLE_NAME);
		return qb.query(db, projection, selection, selectionArgs, null, null,
				sortOrder);
	}

	@Override
	public Uri insert(SQLiteDatabase db, int match, Uri uri,
					  ContentValues values) {
		if (match == MATCH_ITEM) {
			throw new IllegalArgumentException("Not support insert for URI: "
					+ uri);
		}

		Uri result = null;
		final long rowId = db.insert(TABLE_NAME, null, values);
		if (rowId > 0) {
			result = ContentUris.withAppendedId(uri, rowId);
		}
		return result;
	}

	@Override
	public int update(SQLiteDatabase db, int match, Uri uri,
					  ContentValues values, String selection, String[] selectionArgs) {
		if (match == MATCH_ITEM) {
			long id = ContentUris.parseId(uri);
			selection = SQLUtility.and(_ID + "=" + id, selection);
		}
		return db.update(TABLE_NAME, values, selection, selectionArgs);
	}

	@Override
	public int delete(SQLiteDatabase db, int match, Uri uri, String selection,
					  String[] selectionArgs) {
		if (match == MATCH_ITEM) {
			long id = ContentUris.parseId(uri);
			selection = SQLUtility.and(_ID + "=" + id, selection);
		}
		return db.delete(TABLE_NAME, selection, selectionArgs);
	}
}
